const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');

// 使用stealth插件避免被检测
puppeteer.use(StealthPlugin());

class TikTokScraperSmart {
  constructor() {
    this.browser = null;
    this.requestCount = 0;
    this.lastRequestTime = 0;
    this.minDelay = 3000; // 最小间隔3秒
    this.maxDelay = 8000; // 最大间隔8秒
  }

  /**
   * 控制访问频次 - 模拟真实用户行为
   */
  async controlRequestFrequency() {
    const now = Date.now();
    const timeSinceLastRequest = now - this.lastRequestTime;

    // 计算需要等待的时间
    const randomDelay = Math.random() * (this.maxDelay - this.minDelay) + this.minDelay;
    const waitTime = Math.max(0, randomDelay - timeSinceLastRequest);

    if (waitTime > 0) {
      console.log(`访问频次控制: 等待 ${Math.round(waitTime / 1000)} 秒...`);
      await new Promise(resolve => setTimeout(resolve, waitTime));
    }

    this.lastRequestTime = Date.now();
    this.requestCount++;

    // 每10次请求后增加额外延迟
    if (this.requestCount % 10 === 0) {
      const extraDelay = Math.random() * 5000 + 5000; // 5-10秒额外延迟
      console.log(`第${this.requestCount}次请求，额外休息 ${Math.round(extraDelay / 1000)} 秒...`);
      await new Promise(resolve => setTimeout(resolve, extraDelay));
    }
  }

  /**
   * 初始化浏览器
   */
  async initBrowser() {
    if (!this.browser) {
      const launchOptions = {
        headless: false, // 设为false以便调试，生产环境可改为true
        timeout: 60000,
        args: [
          '--no-sandbox',
          '--disable-setuid-sandbox',
          '--disable-dev-shm-usage',
          '--disable-accelerated-2d-canvas',
          '--no-first-run',
          '--no-zygote',
          '--disable-gpu',
          '--disable-web-security',
          '--disable-features=VizDisplayCompositor',
          '--window-size=375,812', // 移动端分辨率 (iPhone 13 Pro)
          '--disable-background-timer-throttling',
          '--disable-backgrounding-occluded-windows',
          '--disable-renderer-backgrounding',
          '--disable-blink-features=AutomationControlled',
          // 禁用媒体权限相关
          '--use-fake-ui-for-media-stream', // 使用假的UI来处理媒体流权限
          '--use-fake-device-for-media-stream', // 使用假设备
          '--disable-user-media-security=true', // 禁用用户媒体安全检查
          '--allow-running-insecure-content', // 允许不安全内容
          '--disable-features=VizDisplayCompositor,AudioServiceOutOfProcess', // 禁用音频进程
          '--autoplay-policy=no-user-gesture-required', // 自动播放策略
          '--disable-ipc-flooding-protection'
        ],
        defaultViewport: {
          width: 375,
          height: 812,
          isMobile: true,
          hasTouch: true,
          deviceScaleFactor: 3
        }
      };

      // macOS特定配置
      if (process.platform === 'darwin') {
        const possiblePaths = [
          '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
          '/Applications/Chromium.app/Contents/MacOS/Chromium'
        ];

        for (const path of possiblePaths) {
          try {
            const fs = require('fs');
            if (fs.existsSync(path)) {
              launchOptions.executablePath = path;
              break;
            }
          } catch (e) {
            // 继续尝试下一个路径
          }
        }
      }

      this.browser = await puppeteer.launch(launchOptions);
    }
    return this.browser;
  }

  /**
   * 创建新页面并设置真实用户环境
   */
  async createPage() {
    const browser = await this.initBrowser();
    const page = await browser.newPage();

    // 设置移动端的用户代理
    await page.setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 17_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/604.1');

    // 设置移动端视窗大小
    await page.setViewport({
      width: 375,
      height: 812,
      isMobile: true,
      hasTouch: true,
      deviceScaleFactor: 3
    });

    // 设置移动端语言和地区
    await page.setExtraHTTPHeaders({
      'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7',
      'Accept-Encoding': 'gzip, deflate, br',
      'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
      'Connection': 'keep-alive',
      'Upgrade-Insecure-Requests': '1',
      'Sec-Fetch-Dest': 'document',
      'Sec-Fetch-Mode': 'navigate',
      'Sec-Fetch-Site': 'none',
      'Cache-Control': 'max-age=0',
      'Sec-CH-UA-Mobile': '?1',
      'Sec-CH-UA-Platform': '"iOS"'
    });

    // 禁用媒体权限请求（摄像头、麦克风等）
    const context = browser.defaultBrowserContext();
    await context.overridePermissions('https://shop.tiktok.com', []);
    await context.overridePermissions('https://www.tiktok.com', []);

    // 禁用页面的媒体权限请求
    await page.evaluateOnNewDocument(() => {
      // 禁用getUserMedia
      if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        navigator.mediaDevices.getUserMedia = () => {
          return Promise.reject(new Error('Permission denied'));
        };
      }

      // 禁用旧版本的getUserMedia
      if (navigator.getUserMedia) {
        navigator.getUserMedia = () => {
          throw new Error('Permission denied');
        };
      }

      // 禁用webkitGetUserMedia
      if (navigator.webkitGetUserMedia) {
        navigator.webkitGetUserMedia = () => {
          throw new Error('Permission denied');
        };
      }

      // 禁用mozGetUserMedia
      if (navigator.mozGetUserMedia) {
        navigator.mozGetUserMedia = () => {
          throw new Error('Permission denied');
        };
      }
    });

    // 设置请求拦截，加速页面加载
    await page.setRequestInterception(true);
    page.on('request', (req) => {
      const resourceType = req.resourceType();
      // 只加载必要的资源
      if (resourceType === 'stylesheet' || resourceType === 'font' || resourceType === 'image') {
        req.abort();
      } else {
        req.continue();
      }
    });

    // 模拟移动端的JavaScript环境
    await page.evaluateOnNewDocument(() => {
      // 移除webdriver标识
      Object.defineProperty(navigator, 'webdriver', {
        get: () => undefined,
      });

      // 模拟移动端的插件
      Object.defineProperty(navigator, 'plugins', {
        get: () => [],
      });

      // 模拟移动端的语言
      Object.defineProperty(navigator, 'languages', {
        get: () => ['en-US', 'en'],
      });

      // 模拟移动端平台
      Object.defineProperty(navigator, 'platform', {
        get: () => 'iPhone',
      });

      // 模拟触摸支持
      Object.defineProperty(navigator, 'maxTouchPoints', {
        get: () => 5,
      });

      // 模拟移动端的userAgent检测
      Object.defineProperty(navigator, 'userAgent', {
        get: () => 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Mobile/15E148 Safari/604.1',
      });
    });

    return page;
  }

  /**
   * 等待指定时间（替代waitForTimeout）
   */
  async wait(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * 智能等待页面加载完成
   */
  async waitForPageLoad(page, timeout = 10000) {
    try {
      // 等待网络空闲（Puppeteer方式）
      await page.waitForFunction(
        () => {
          // 检查页面是否基本加载完成
          return document.readyState === 'complete' ||
            document.readyState === 'interactive';
        },
        { timeout }
      );
      console.log('页面加载状态检查完成');
    } catch (e) {
      console.log('页面加载检查超时，使用固定等待时间...');
      await this.wait(3000);
    }
  }

  /**
   * 等待元素出现或超时
   */
  async waitForElementOrTimeout(page, selector, timeout = 5000) {
    try {
      await page.waitForSelector(selector, { timeout });
      return true;
    } catch (e) {
      return false;
    }
  }

  /**
   * 处理TikTok App推广弹窗
   */
  async handleAppPromotionModal(page) {
    try {
      console.log('检查是否有App推广弹窗...');

      // 等待页面加载完成
      await this.wait(2000);

      // 查找"Not now"按钮的多种可能选择器
      const notNowSelectors = [
        'button:contains("Not now")',
        'button:contains("not now")',
        'button:contains("Not Now")',
        '[data-testid="modal-close"]',
        '[class*="modal"] button:contains("Not")',
        '[class*="popup"] button:contains("Not")',
        'button[class*="secondary"]',
        '.modal-footer button:last-child',
        '[role="dialog"] button:last-child'
      ];

      // 尝试点击关闭按钮（X）
      const closeSelectors = [
        'button[aria-label="Close"]',
        'button[aria-label="close"]',
        '[class*="close"]',
        '[class*="Close"]',
        'svg[class*="close"]',
        '.modal-header button',
        '[role="dialog"] button:first-child'
      ];

      let modalClosed = false;

      // 首先尝试点击"Not now"按钮
      for (const selector of notNowSelectors) {
        try {
          const element = await page.$(selector);
          if (element) {
            console.log(`找到"Not now"按钮: ${selector}`);

            // 模拟人类点击行为
            await this.humanLikeClick(page, element);
            await this.wait(1000);

            // 检查弹窗是否消失
            const modalStillExists = await page.$('[role="dialog"], .modal, [class*="modal"], [class*="popup"]');
            if (!modalStillExists) {
              console.log('App推广弹窗已关闭');
              modalClosed = true;
              break;
            }
          }
        } catch (e) {
          // 继续尝试下一个选择器
        }
      }

      // 如果"Not now"没有成功，尝试关闭按钮
      if (!modalClosed) {
        for (const selector of closeSelectors) {
          try {
            const element = await page.$(selector);
            if (element) {
              console.log(`找到关闭按钮: ${selector}`);
              await this.humanLikeClick(page, element);
              await this.wait(1000);

              const modalStillExists = await page.$('[role="dialog"], .modal, [class*="modal"], [class*="popup"]');
              if (!modalStillExists) {
                console.log('弹窗已通过关闭按钮关闭');
                modalClosed = true;
                break;
              }
            }
          } catch (e) {
            // 继续尝试下一个选择器
          }
        }
      }

      // 如果还是没有关闭，尝试按ESC键
      if (!modalClosed) {
        console.log('尝试按ESC键关闭弹窗...');
        await page.keyboard.press('Escape');
        await this.wait(1000);
      }

      return modalClosed;

    } catch (error) {
      console.error('处理App推广弹窗时出错:', error);
      return false;
    }
  }

  /**
   * 模拟人类点击行为
   */
  async humanLikeClick(page, element) {
    // 获取元素位置
    const box = await element.boundingBox();
    if (!box) return;

    // 计算点击位置（元素中心附近的随机位置）
    const x = box.x + box.width / 2 + (Math.random() - 0.5) * 10;
    const y = box.y + box.height / 2 + (Math.random() - 0.5) * 10;

    // 模拟鼠标移动到元素
    await page.mouse.move(x, y, { steps: Math.floor(Math.random() * 5) + 3 });
    await this.wait(100 + Math.random() * 200);

    // 点击
    await page.mouse.click(x, y);
    await this.wait(50 + Math.random() * 100);
  }

  /**
   * 处理各种验证码
   */
  async handleCaptcha(page) {
    try {
      console.log('检测验证码类型...');

      // 检查是否有"Verify to continue"文本
      const verifyText = await page.evaluate(() => {
        const elements = document.querySelectorAll('*');
        for (let el of elements) {
          if (el.textContent && el.textContent.includes('Verify to continue')) {
            return true;
          }
        }
        return false;
      });

      if (verifyText) {
        console.log('发现验证页面："Verify to continue"');

        // 检查是否是拼图验证
        const puzzleText = await page.evaluate(() => {
          const elements = document.querySelectorAll('*');
          for (let el of elements) {
            if (el.textContent && el.textContent.includes('Drag the puzzle piece')) {
              return true;
            }
          }
          return false;
        });

        if (puzzleText) {
          console.log('发现拼图验证码');
          return await this.handlePuzzleCaptcha(page);
        }
      }

      // 检查滑块验证
      const captchaSelectors = [
        '.captcha_verify_container',
        '.verify-slider',
        '.slider-track',
        '[class*="slider"]',
        '[class*="captcha"]',
        '[class*="verify"]'
      ];

      let captchaFound = false;
      for (const selector of captchaSelectors) {
        const element = await page.$(selector);
        if (element) {
          captchaFound = true;
          console.log(`发现滑块验证: ${selector}`);
          break;
        }
      }

      if (captchaFound) {
        return await this.handleSliderCaptcha(page);
      }

      return true; // 没有验证码

    } catch (error) {
      console.error('处理验证码时出错:', error);
      return false;
    }
  }

  /**
   * 处理拼图验证码
   */
  async handlePuzzleCaptcha(page) {
    try {
      console.log('开始处理拼图验证码...');

      // 等待验证码完全加载
      await this.wait(3000);

      // 尝试多种策略处理拼图验证
      const strategies = [
        () => this.tryPuzzleByDragging(page),
        () => this.tryPuzzleByClicking(page),
        () => this.tryRefreshAndSkip(page)
      ];

      for (let i = 0; i < strategies.length; i++) {
        console.log(`尝试拼图验证策略 ${i + 1}...`);

        try {
          const result = await strategies[i]();
          if (result) {
            console.log(`策略 ${i + 1} 成功`);
            return true;
          }
        } catch (error) {
          console.log(`策略 ${i + 1} 失败:`, error.message);
        }

        // 等待一下再尝试下一个策略
        await this.wait(2000);
      }

      console.log('所有拼图验证策略都失败了');
      return false;

    } catch (error) {
      console.error('处理拼图验证码时出错:', error);
      return false;
    }
  }

  /**
   * 策略1: 通过拖拽处理拼图
   */
  async tryPuzzleByDragging(page) {
    // 查找可拖拽的元素
    const draggableSelectors = [
      '[class*="puzzle"]',
      '[class*="piece"]',
      '[class*="drag"]',
      'img[draggable="true"]',
      'canvas',
      '[style*="cursor: grab"]',
      '[style*="cursor: pointer"]'
    ];

    for (const selector of draggableSelectors) {
      try {
        const element = await page.$(selector);
        if (element) {
          const box = await element.boundingBox();
          if (box) {
            console.log(`尝试拖拽元素: ${selector}`);

            // 尝试多个方向的拖拽
            const directions = [
              { x: 200, y: 0 },   // 向右
              { x: 150, y: 0 },   // 向右（短距离）
              { x: 100, y: 50 },  // 向右下
              { x: 0, y: 100 }    // 向下
            ];

            for (const dir of directions) {
              const startX = box.x + box.width / 2;
              const startY = box.y + box.height / 2;
              const endX = startX + dir.x;
              const endY = startY + dir.y;

              await this.humanLikeDrag(page, startX, startY, endX, endY);
              await this.wait(2000);

              // 检查是否成功
              const success = await this.checkVerificationSuccess(page);
              if (success) return true;
            }
          }
        }
      } catch (e) {
        continue;
      }
    }

    return false;
  }

  /**
   * 策略2: 通过点击处理拼图
   */
  async tryPuzzleByClicking(page) {
    // 查找可点击的按钮或区域
    const clickableSelectors = [
      'button',
      '[role="button"]',
      '.refresh',
      '.reload',
      '[class*="refresh"]',
      '[class*="reload"]',
      '[class*="retry"]'
    ];

    for (const selector of clickableSelectors) {
      try {
        const elements = await page.$$(selector);
        for (const element of elements) {
          const text = await page.evaluate(el => el.textContent?.toLowerCase() || '', element);

          // 查找刷新或重试按钮
          if (text.includes('refresh') || text.includes('reload') || text.includes('retry')) {
            console.log(`点击刷新按钮: ${text}`);
            await this.humanLikeClick(page, element);
            await this.wait(3000);

            const success = await this.checkVerificationSuccess(page);
            if (success) return true;
          }
        }
      } catch (e) {
        continue;
      }
    }

    return false;
  }

  /**
   * 策略3: 刷新页面并尝试跳过
   */
  async tryRefreshAndSkip(page) {
    console.log('尝试刷新页面跳过验证...');

    try {
      await page.reload({ waitUntil: 'domcontentloaded' });
      await this.wait(5000);

      // 检查是否跳过了验证
      const success = await this.checkVerificationSuccess(page);
      return success;

    } catch (error) {
      console.log('刷新页面失败');
      return false;
    }
  }

  /**
   * 检查验证是否成功
   */
  async checkVerificationSuccess(page) {
    try {
      const hasVerifyText = await page.evaluate(() => {
        return document.body.textContent.includes('Verify to continue') ||
          document.body.textContent.includes('Drag the puzzle piece');
      });

      return !hasVerifyText;
    } catch (error) {
      return false;
    }
  }

  /**
   * 人类化拖拽操作
   */
  async humanLikeDrag(page, startX, startY, endX, endY) {
    try {
      // 移动到起点
      await page.mouse.move(startX, startY);
      await this.wait(200 + Math.random() * 300);

      // 按下鼠标
      await page.mouse.down();
      await this.wait(100 + Math.random() * 200);

      // 分段拖拽，模拟人类行为
      const steps = Math.floor(Math.random() * 8) + 12; // 12-20步
      const deltaX = endX - startX;
      const deltaY = endY - startY;

      for (let i = 1; i <= steps; i++) {
        const progress = i / steps;
        // 使用缓动函数
        const easeProgress = this.easeOutCubic(progress);

        const currentX = startX + (deltaX * easeProgress);
        const currentY = startY + (deltaY * easeProgress);

        // 添加轻微的随机抖动
        const jitterX = currentX + (Math.random() - 0.5) * 4;
        const jitterY = currentY + (Math.random() - 0.5) * 4;

        await page.mouse.move(jitterX, jitterY, { steps: 2 });

        // 随机延迟
        const delay = Math.random() * 80 + 40;
        await this.wait(delay);
      }

      // 释放鼠标
      await page.mouse.up();
      await this.wait(300 + Math.random() * 500);

    } catch (error) {
      console.error('拖拽操作失败:', error);
    }
  }

  /**
   * 处理滑块验证
   */
  async handleSliderCaptcha(page) {
    try {
      console.log('开始处理滑块验证...');

      // 查找滑块和轨道
      const sliderSelectors = [
        '.secsdk-captcha-drag-icon',
        '.slider-btn',
        '[class*="drag"]',
        '[class*="slider-btn"]'
      ];

      const trackSelectors = [
        '.secsdk-captcha-drag-track',
        '.slider-track',
        '[class*="track"]'
      ];

      let slider = null;
      let track = null;

      for (const selector of sliderSelectors) {
        slider = await page.$(selector);
        if (slider) break;
      }

      for (const selector of trackSelectors) {
        track = await page.$(selector);
        if (track) break;
      }

      if (slider && track) {
        console.log('开始处理滑块验证...');
        const success = await this.solveSliderCaptcha(page, slider, track);
        return success;
      }

      console.log('未找到滑块元素');
      return false;

    } catch (error) {
      console.error('处理滑块验证时出错:', error);
      return false;
    }
  }

  /**
   * 解决滑块验证
   */
  async solveSliderCaptcha(page, slider, track) {
    try {
      const sliderBox = await slider.boundingBox();
      const trackBox = await track.boundingBox();

      if (!sliderBox || !trackBox) {
        return false;
      }

      // 计算滑动距离
      const distance = trackBox.width - sliderBox.width - 10; // 留一点余量

      console.log(`滑块验证 - 需要滑动距离: ${distance}px`);

      // 移动到滑块
      const startX = sliderBox.x + sliderBox.width / 2;
      const startY = sliderBox.y + sliderBox.height / 2;

      await page.mouse.move(startX, startY);
      await this.wait(500 + Math.random() * 500);

      // 按下鼠标
      await page.mouse.down();
      await this.wait(100 + Math.random() * 100);

      // 分段滑动，模拟人类行为
      const steps = Math.floor(Math.random() * 5) + 8; // 8-12步
      const stepDistance = distance / steps;

      for (let i = 1; i <= steps; i++) {
        const progress = i / steps;
        // 使用缓动函数模拟真实滑动
        const easeProgress = this.easeOutCubic(progress);
        const currentX = startX + (distance * easeProgress);

        // 添加轻微的Y轴抖动
        const jitterY = startY + (Math.random() - 0.5) * 3;

        await page.mouse.move(currentX, jitterY, { steps: 2 });

        // 随机延迟
        const delay = Math.random() * 50 + 30;
        await this.wait(delay);
      }

      // 释放鼠标
      await page.mouse.up();
      await this.wait(1000);

      // 检查验证是否成功
      await this.wait(2000);
      const captchaStillExists = await page.$('.captcha_verify_container, .verify-slider');

      if (!captchaStillExists) {
        console.log('滑块验证成功');
        return true;
      } else {
        console.log('滑块验证失败');
        return false;
      }

    } catch (error) {
      console.error('解决滑块验证时出错:', error);
      return false;
    }
  }

  /**
   * 缓动函数 - 模拟真实的滑动曲线
   */
  easeOutCubic(t) {
    return 1 - Math.pow(1 - t, 3);
  }

  /**
   * 快速检测页面错误信息
   */
  async detectPageErrors(page) {
    try {
      // 快速检测常见的错误页面，设置短超时避免长时间等待
      const errorMessages = await Promise.race([
        page.evaluate(() => {
          const bodyText = document.body.textContent || '';
          const titleText = document.title || '';
          const allText = bodyText + ' ' + titleText;

          // 检测地区限制错误（最常见的错误）
          if (allText.includes('Product not available in this country or region') ||
            allText.includes("This product isn't currently available in your country or region") ||
            allText.includes('商品在您所在的国家或地区不可用') ||
            allText.includes('此商品目前在您的国家或地区不可用') ||
            allText.includes('not available in this country')) {
            return {
              type: 'REGION_RESTRICTED',
              message: 'Product not available in this country or region'
            };
          }

          // 检测商品不存在错误（更精确的检测）
          if (allText.includes('Product not found') ||
            allText.includes('Page not found') ||
            allText.includes('商品不存在') ||
            allText.includes('页面不存在') ||
            titleText.includes('404') ||
            titleText.includes('Not Found')) {
            return {
              type: 'PRODUCT_NOT_FOUND',
              message: 'Product not found or page does not exist'
            };
          }

          // 检测404错误页面特征（更严格的检测）
          const is404Page = (
            (titleText.toLowerCase().includes('404') || titleText.toLowerCase().includes('not found')) ||
            (allText.includes('404') && allText.includes('not found') && allText.length < 1000) ||
            (allText.includes('404') && allText.includes('page') && allText.includes('error'))
          );

          if (is404Page) {
            return {
              type: 'PRODUCT_NOT_FOUND',
              message: 'Product not found or page does not exist'
            };
          }

          // 检测商品已下架
          if (allText.includes('Product is no longer available') ||
            allText.includes('This product has been removed') ||
            allText.includes('商品已下架') ||
            allText.includes('商品不再可用') ||
            allText.includes('no longer available')) {
            return {
              type: 'PRODUCT_UNAVAILABLE',
              message: 'Product is no longer available'
            };
          }

          // 检测访问被限制
          if (allText.includes('Access denied') ||
            allText.includes('Forbidden') ||
            allText.includes('访问被拒绝') ||
            allText.includes('禁止访问') ||
            titleText.includes('Forbidden')) {
            return {
              type: 'ACCESS_DENIED',
              message: 'Access to this page is denied'
            };
          }

          // 检测需要登录
          if (allText.includes('Please log in') ||
            allText.includes('Sign in required') ||
            allText.includes('请登录') ||
            allText.includes('需要登录') ||
            allText.includes('Login required')) {
            return {
              type: 'LOGIN_REQUIRED',
              message: 'Login required to access this page'
            };
          }

          // 检测网络连接错误
          if (allText.includes('无法访问此网站') ||
            allText.includes('This site can\'t be reached') ||
            allText.includes('ERR_NAME_NOT_RESOLVED') ||
            allText.includes('ERR_CONNECTION_REFUSED') ||
            allText.includes('ERR_CONNECTION_TIMED_OUT') ||
            allText.includes('ERR_NETWORK_CHANGED') ||
            allText.includes('ERR_INTERNET_DISCONNECTED') ||
            allText.includes('Check your internet connection') ||
            allText.includes('检查您的互联网连接') ||
            allText.includes('网络连接出现问题') ||
            allText.includes('Connection timed out') ||
            titleText.includes('无法访问此网站') ||
            titleText.includes('This site can\'t be reached')) {
            return {
              type: 'NETWORK_ERROR',
              message: '无法访问此网站，网络连接出现问题'
            };
          }

          // 检测DNS解析错误
          if (allText.includes('DNS_PROBE_FINISHED_NXDOMAIN') ||
            allText.includes('DNS解析失败') ||
            allText.includes('找不到服务器') ||
            allText.includes('Server not found') ||
            allText.includes('could not be found')) {
            return {
              type: 'DNS_ERROR',
              message: 'DNS解析失败，无法找到服务器'
            };
          }

          return null;
        }),
        // 设置1秒超时，避免长时间等待
        new Promise(resolve => setTimeout(() => resolve(null), 1000))
      ]);

      if (errorMessages) {
        console.log(`快速检测到页面错误: ${errorMessages.type} - ${errorMessages.message}`);
        return errorMessages;
      }

      return null;

    } catch (error) {
      console.error('快速检测页面错误时出错:', error);
      return null;
    }
  }

  /**
   * 提取商品标题
   */
  async extractProductTitle(page) {
    try {
      console.log('开始提取商品标题...');

      // 首先检测页面是否有错误
      const pageError = await this.detectPageErrors(page);
      if (pageError) {
        console.log(`检测到页面错误: ${pageError.type} - ${pageError.message}`);
        return {
          error: pageError.type,
          message: pageError.message,
          isError: true
        };
      }

      // 等待页面内容加载
      console.log('等待商品信息充分加载...');
      await this.wait(5000); // 增加等待时间到5秒

      const titleSelectors = [
        'h1[data-testid="pdp-product-title"]',
        '.product-title',
        'h1.title',
        '[data-testid="product-title"]',
        'h1',
        '.pdp-product-title',
        '[class*="product-title"]',
        '[class*="ProductTitle"]',
        '[data-e2e="product-title"]',
        // 从图片中看到的可能选择器
        '.product-name',
        '.item-title',
        '[class*="title"]'
      ];

      // 尝试多次提取，因为内容可能需要时间加载
      for (let attempt = 1; attempt <= 3; attempt++) {
        console.log(`第${attempt}次尝试提取标题...`);

        // 每次尝试前都检查一下是否有错误页面
        const pageError = await this.detectPageErrors(page);
        if (pageError) {
          console.log(`检测到页面错误: ${pageError.type} - ${pageError.message}`);
          return {
            error: pageError.type,
            message: pageError.message,
            isError: true
          };
        }

        for (const selector of titleSelectors) {
          try {
            // 等待元素出现
            const elementExists = await this.waitForElementOrTimeout(page, selector, 2000);
            if (elementExists) {
              const element = await page.$(selector);
              if (element) {
                const title = await page.evaluate(el => el.textContent?.trim(), element);
                if (title && title.length > 5 && !title.toLowerCase().includes('tiktok shop')) {
                  console.log(`找到商品标题 (${selector}): ${title}`);
                  return title;
                }
              }
            }
          } catch (e) {
            // 继续尝试下一个选择器
          }
        }

        // 如果这次没找到，等待一下再试
        if (attempt < 3) {
          console.log('未找到标题，等待页面继续加载...');
          await this.wait(4000); // 增加等待时间到4秒
        }
      }

      // 尝试从页面标题中提取
      try {
        const pageTitle = await page.title();
        if (pageTitle && !pageTitle.toLowerCase().includes('tiktok shop')) {
          const cleanTitle = pageTitle.replace(/\s*\|\s*TikTok Shop.*$/i, '').trim();
          if (cleanTitle.length > 5) {
            console.log(`从页面标题提取: ${cleanTitle}`);
            return cleanTitle;
          }
        }
      } catch (e) {
        console.log('获取页面标题失败');
      }

      // 最后尝试：获取页面所有文本，寻找可能的商品标题
      try {
        console.log('尝试从页面内容中查找标题...');
        const allText = await page.evaluate(() => {
          const elements = document.querySelectorAll('h1, h2, .title, [class*="title"], [class*="product"], [class*="name"]');
          return Array.from(elements).map(el => el.textContent?.trim()).filter(text =>
            text && text.length > 10 && text.length < 200 &&
            !text.toLowerCase().includes('tiktok') &&
            !text.toLowerCase().includes('shop') &&
            !text.toLowerCase().includes('login') &&
            !text.toLowerCase().includes('sign')
          );
        });

        if (allText.length > 0) {
          console.log(`从页面内容找到可能的标题: ${allText[0]}`);
          return allText[0];
        }
      } catch (e) {
        console.log('从页面内容提取标题失败');
      }

      console.log('未找到商品标题');
      return null;

    } catch (error) {
      console.error('提取商品标题时出错:', error);
      return null;
    }
  }

  /**
   * 爬取商品信息（主要是标题）
   */
  async scrapeProductInfo(url) {
    let page = null;

    try {
      console.log(`开始智能爬取: ${url}`);

      // 控制访问频次
      await this.controlRequestFrequency();

      page = await this.createPage();

      console.log('正在访问页面...');

      // 设置更宽松的加载策略
      try {
        await page.goto(url, {
          waitUntil: 'domcontentloaded', // 改为更快的加载策略
          timeout: 45000
        });
        console.log('页面导航完成');
      } catch (gotoError) {
        console.log('页面加载出现错误:', gotoError.message);

        // 检查是否是网络连接错误
        if (gotoError.message.includes('ERR_NAME_NOT_RESOLVED') ||
          gotoError.message.includes('ERR_CONNECTION_REFUSED') ||
          gotoError.message.includes('ERR_CONNECTION_TIMED_OUT') ||
          gotoError.message.includes('ERR_NETWORK_CHANGED') ||
          gotoError.message.includes('ERR_INTERNET_DISCONNECTED') ||
          gotoError.message.includes('net::ERR_') ||
          gotoError.message.includes('Navigation timeout')) {
          console.log('检测到网络连接错误，直接返回');
          return {
            title: '无法访问此网站，网络连接出现问题',
            success: false,
            error: 'NETWORK_ERROR',
            message: '无法访问此网站，网络连接出现问题',
            requestCount: this.requestCount,
            isPageError: true
          };
        }

        // 如果不是明确的网络错误，继续尝试处理已加载的内容
        console.log('页面加载超时，尝试直接处理已加载的内容...');
      }

      // 快速检测页面基本内容
      console.log('等待页面内容加载...');
      await this.wait(5000); // 增加到5秒让页面充分加载

      // 尝试等待关键元素出现
      const keyElementExists = await this.waitForElementOrTimeout(page, 'h1, .product-title, [data-testid="pdp-product-title"], title', 8000);
      if (keyElementExists) {
        console.log('检测到关键元素，页面加载完成');
      } else {
        console.log('未检测到关键元素，但继续处理');
        // 再额外等待一段时间
        await this.wait(3000);
      }

      // 立即检测是否是错误页面
      const quickErrorCheck = await this.detectPageErrors(page);
      if (quickErrorCheck) {
        console.log(`快速检测到页面错误，立即返回: ${quickErrorCheck.type} - ${quickErrorCheck.message}`);
        return {
          title: quickErrorCheck.message,
          success: false,
          error: quickErrorCheck.type,
          message: quickErrorCheck.message,
          requestCount: this.requestCount,
          isPageError: true
        };
      }

      // 如果不是错误页面，继续正常处理
      console.log('未检测到页面错误，继续正常处理...');

      // 等待基本内容出现
      const hasContent = await this.waitForElementOrTimeout(page, 'body', 5000);
      if (!hasContent) {
        console.log('页面内容加载异常');
        // 即使检测不到body，也继续尝试处理
      }

      // 等待页面更多内容加载
      console.log('等待页面充分加载...');
      await this.wait(3000); // 额外等待3秒

      // 处理App推广弹窗
      await this.handleAppPromotionModal(page);

      // 再次等待，确保弹窗处理完成且页面内容稳定
      console.log('弹窗处理完成，等待页面稳定...');
      await this.wait(4000); // 增加等待时间到4秒

      // 再次快速检测错误页面（防止重定向后出现错误）
      const secondErrorCheck = await this.detectPageErrors(page);
      if (secondErrorCheck) {
        console.log(`处理弹窗后检测到页面错误，立即返回: ${secondErrorCheck.type} - ${secondErrorCheck.message}`);
        return {
          title: secondErrorCheck.message,
          success: false,
          error: secondErrorCheck.type,
          message: secondErrorCheck.message,
          requestCount: this.requestCount,
          isPageError: true
        };
      }

      // 检查并处理各种验证码
      const captchaHandled = await this.handleCaptcha(page);
      if (!captchaHandled) {
        console.log('验证码处理失败，但不重试以避免重定向');
        // 不再刷新页面重试，直接返回验证码错误
        return {
          title: 'Verify to continue',
          success: false,
          error: 'CAPTCHA_REQUIRED',
          message: '需要人工验证',
          requestCount: this.requestCount
        };
      }

      // 验证码处理后再次检查错误页面
      const thirdErrorCheck = await this.detectPageErrors(page);
      if (thirdErrorCheck) {
        console.log(`验证码处理后检测到页面错误，立即返回: ${thirdErrorCheck.type} - ${thirdErrorCheck.message}`);
        return {
          title: thirdErrorCheck.message,
          success: false,
          error: thirdErrorCheck.type,
          message: thirdErrorCheck.message,
          requestCount: this.requestCount,
          isPageError: true
        };
      }

      // 最后检查是否仍在验证页面
      const stillInVerification = await page.evaluate(() => {
        return document.body.textContent.includes('Verify to continue') ||
          document.body.textContent.includes('Drag the puzzle piece');
      });

      if (stillInVerification) {
        console.log('仍在验证页面，无法继续');
        return {
          title: 'Verify to continue',
          success: false,
          error: 'CAPTCHA_REQUIRED',
          message: '需要人工验证',
          requestCount: this.requestCount
        };
      }

      // 提取商品标题
      const titleResult = await this.extractProductTitle(page);

      // 检查是否是错误页面
      if (titleResult && titleResult.isError) {
        console.log(`页面错误: ${titleResult.error} - ${titleResult.message}`);
        return {
          title: titleResult.message,
          success: false,
          error: titleResult.error,
          message: titleResult.message,
          requestCount: this.requestCount,
          isPageError: true
        };
      }

      if (titleResult && typeof titleResult === 'string') {
        console.log('商品信息提取成功');
        return {
          title: titleResult,
          success: true,
          timestamp: new Date().toISOString(),
          requestCount: this.requestCount
        };
      } else {
        return {
          title: '未找到商品标题',
          success: false,
          error: 'TITLE_NOT_FOUND',
          requestCount: this.requestCount
        };
      }

    } catch (error) {
      console.error('智能爬取失败:', error);
      return {
        title: '爬取失败',
        success: false,
        error: error.message,
        requestCount: this.requestCount
      };
    } finally {
      if (page) {
        await page.close();
      }
    }
  }

  /**
   * 从链接提取商品ID
   */
  extractProductId(url) {
    try {
      const regex = /\/product\/(\d+)/;
      const match = url.match(regex);
      return match ? match[1] : null;
    } catch (error) {
      console.error('提取商品ID失败:', error);
      return null;
    }
  }

  /**
   * 关闭浏览器
   */
  async closeBrowser() {
    if (this.browser) {
      await this.browser.close();
      this.browser = null;
      console.log('浏览器已关闭');
    }
  }

  /**
   * 获取统计信息
   */
  getStats() {
    return {
      requestCount: this.requestCount,
      lastRequestTime: this.lastRequestTime,
      uptime: Date.now() - (this.lastRequestTime - this.requestCount * 5000) // 估算
    };
  }
}

module.exports = new TikTokScraperSmart();